<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <meta name="keywords" content="天地图"/>
    <title>天地图－地图API－范例－画面</title>
    <script type="text/javascript" src="http://api.tianditu.gov.cn/api?v=4.0&tk=95f0a5688ec713adb3dd1735533f6fcb"></script>
    <script type="text/javascript" src="turf.min.js"></script>
    <script type="text/javascript" src="lodash.min.js"></script>
    <style type="text/css">body,html{width:100%;height:100%;margin:0;font-family:"Microsoft YaHei"}#mapDiv{width:100%;height:800px}input,b,p{margin-left:5px;font-size:14px}</style>
    <script>
    let map;
    let cells = [];
    let index = 0;
    let isDelete = false;
    function onLoad() {
        map = new T.Map("mapDiv");
        map.disableScrollWheelZoom();
        map.disableDoubleClickZoom();
        map.centerAndZoom(new T.LngLat(116.40969, 39.94940), 12);
        update();
    }
    function update() {
        map.clearOverLays();
        for (const cell of cells) {
            const polygon = new T.Polygon(cell.points, {
                color: "black",
                weight: 1,
                opacity: 0.5,
                fillColor: cell.color,
                fillOpacity: 0.5
            });
            polygon.addEventListener('click', (e) => {
                if (isDelete) {
                    isDelete = false;
                    cells = _.filter(cells, o=>o.index!==cell.index);
                    update();
                } else {
                    console.log("=======", cell.points);
                }
            });
            cell.polygon = polygon;
            map.addOverLay(polygon);

            const label = new T.Label({
                text: cell.name,
                position: getCenterLatlng(cell.points),
                offset: new T.Point(-30, -20),
            });
            map.addOverLay(label);
        }
    }
    function enableEdit() {
        for (const cell of cells) {
            cell.polygon.enableEdit();
        }
    }
    function disableEdit() {
        for (const cell of cells) {
            cell.points = cell.polygon.getLngLats()[0];
            cell.polygon.disableEdit();
        }
        update();
    }
    function createNewPolygon() {
        const color = randomColor();
        const tool = new T.PolygonTool(map, {
            color: 'red',
            weight: 1,
            opacity: 0.7,
            fillColor: color,
            fillOpacity: 0.3,
            lineStyle: 'solid',
            showLabel: false,
        });
        tool.addEventListener('draw', (e) => {
            cells.push({ points: e.currentLnglats, color, name: `网格${index}`, index });
            index++;
            tool.close();
            update();
        });
        tool.open();
    }
    function splitPolygon() {
        const tool = new T.PolylineTool(map, {
            color: 'blue',
            weight: 2,
            opacity: 0.7,
            lineStyle: 'solid',
            showLabel: false,
        });
        tool.addEventListener('draw', (e) => {
            split(e.currentLnglats, cells);
            tool.close();
            update();
        });
        tool.open();
    }
    function mergePolygon() {
        const tool = new T.PolylineTool(map, {
            color: 'blue',
            weight: 2,
            opacity: 0.7,
            lineStyle: 'solid',
            showLabel: false,
        });
        tool.addEventListener('draw', (e) => {
            merge(e.currentLnglats, cells);
            tool.close();
            update();
        });
        tool.open();
    }
    function deletePolygon() {
        isDelete = true;
    }
    function clearOverLays(){
        cells = [];
        map.clearOverLays();
    }
    function getCenterLatlng(points){
        const list = [];
        for (const point of points) {
            list.push(turf.point([ point.getLng(), point.getLat() ]));
        }
        const features = turf.featureCollection(list);
        const center = turf.getCoord(turf.center(features));
        return new T.LngLat(...center);
    }
    function randomColor(){
        return "#"+("00000"+((Math.random()*16777215+0.5)>>0).toString(16)).slice(-6);
    }
    function lineCoordinatesJoin(line1, line2) {
        line1.geometry.coordinates = line1.geometry.coordinates.concat(line2.geometry.coordinates);
        return line1;
    }
    function lineJoin(line1, line2) {
        const coords1 = turf.getCoords(line1);
        const coords2 = turf.getCoords(line2);
        const point10 = _.first(coords1);
        const point20 = _.first(coords2);
        const point21 = _.last(coords2);
        const len1 = turf.distance(point20, point10);
        const len2 = turf.distance(point21, point10);
        if (len1 < len2) {
            line1.geometry.coordinates = line1.geometry.coordinates.concat(_.reverse([...line2.geometry.coordinates]));
        } else {
            line1.geometry.coordinates = line1.geometry.coordinates.concat(line2.geometry.coordinates);
        }
        return turf.lineToPolygon(line1);
    }
    function split(line, __cells) {
        line = turf.lineString(line.map(o=>[o.getLng(), o.getLat()]));
        const _cells = [];
        for (const cell of __cells) {
            const polygon = turf.polygon([[...cell.points.map(o=>[o.getLng(), o.getLat()]), [cell.points[0].getLng(), cell.points[0].getLat()]]]);
            const pline = turf.polygonToLine(polygon);
            const intersect = turf.lineIntersect(pline, line);
            if (intersect.features.length !== 2) {
                _cells.push(cell);
                continue;
            }
            const psplit = turf.lineSplit(pline, line);
            const lsplit = turf.lineSplit(line, pline);
            const polygonLine1 = psplit.features[1];
            const polygonLine2 = lineCoordinatesJoin(psplit.features[2], psplit.features[0]);
            let splitLine = _.find(lsplit.features, o=>turf.booleanContains(polygon, o));
            const polygon1 = lineJoin(polygonLine1, splitLine);
            const polygon2 = lineJoin(polygonLine2, splitLine);
            _cells.push({ ...cell, points: turf.getCoords(polygon1)[0].map(o=>new T.LngLat(o[0], o[1])) });
            _cells.push({ points: turf.getCoords(polygon2)[0].map(o=>new T.LngLat(o[0], o[1])), color: randomColor(), name: `网格${index}`, index });
            index++;
        }
        cells = _cells;
    }
    function merge(line, __cells) {
        const coords = line.map(o=>[o.getLng(), o.getLat()]);
        const point0 = turf.point(_.first(coords));
        const point1 = turf.point(_.last(coords));
        let polygon1, polygon2, cell1, cell2, points;
        for (const cell of __cells) {
            const polygon = turf.polygon([[...cell.points.map(o=>[o.getLng(), o.getLat()]), [cell.points[0].getLng(), cell.points[0].getLat()]]]);
            if (turf.booleanPointInPolygon(point0, polygon)) {
                polygon1 = polygon;
                cell1 = cell;
            } else if (turf.booleanPointInPolygon(point1, polygon)) {
                polygon2 = polygon;
                cell2 = cell;
            }
            if (polygon1 !== undefined && polygon2 !== undefined) {
                const union = turf.union(polygon1, polygon2);
                const c1 = cell1.index < cell2.index ? cell1 : cell2;
                const c2 = cell1.index < cell2.index ? cell2 : cell1;
                c1.points = turf.getCoords(union)[0].map(o=>new T.LngLat(o[0], o[1]));
                cells = _.filter(cells, o=>o.index!==c2.index);
                break;
            }
        }
    }
    </script>
</head>
<body onLoad="onLoad()">
    <div id="mapDiv" ></div>
</div>
<div style="margin-top:10px">
    <input type="button" value="启动编辑" onclick="enableEdit();">
    <input type="button" value="完成编辑" onclick="disableEdit();"/>
    <input type="button" value="增加区域" onclick="createNewPolygon();"/>
    <input type="button" value="分割区域" onclick="splitPolygon();"/>
    <input type="button" value="合并区域" onclick="mergePolygon();"/>
    <input type="button" value="删除区域" onclick="deletePolygon();"/>
    <input type="button" value="清除所有" onClick='clearOverLays()'/>
</div>
</body>
</html>
